package com.imooc.pan.server.modules.file.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.imooc.pan.core.exception.RPanBusinessException;
import com.imooc.pan.core.utils.IdUtil;
import com.imooc.pan.server.common.config.PanServerConfig;
import com.imooc.pan.server.modules.file.context.FileChunkSaveContext;
import com.imooc.pan.server.modules.file.converter.FileConverter;
import com.imooc.pan.server.modules.file.entity.RPanFileChunk;
import com.imooc.pan.server.modules.file.enums.MergeFlagEnum;
import com.imooc.pan.server.modules.file.mapper.RPanFileChunkMapper;
import com.imooc.pan.server.modules.file.service.RPanFileChunkService;
import com.imooc.pan.storage.engine.core.StorageEngine;
import com.imooc.pan.storage.engine.core.context.StoreFileChunkContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;

/**
* @author 86156
* @description 针对表【r_pan_file_chunk(文件分片信息表)】的数据库操作Service实现
* @createDate 2025-04-03 17:03:23
*/
@Service
public class RPanFileChunkServiceImpl extends ServiceImpl<RPanFileChunkMapper, RPanFileChunk>
implements RPanFileChunkService {
    @Autowired
    private FileConverter fileConverter;

    @Autowired
    private StorageEngine storageEngine;
    @Autowired
    private PanServerConfig config;
    /**
     * 1. 保存文件分片和记录
     * 2. 判断文件分片是否全部上传完成
     * @param context
     */
    @Override
    public void saveChunkFile(FileChunkSaveContext context) {
        doSaveChunkFile(context);
        doJudgeMergeFile(context);
    }

    /**
     * 执行文件上传保存的操作
     * 1.委托文件存储引擎存储文件分片
     * 2.保存文件分片记录
     * @param context
     */
    private void doSaveChunkFile(FileChunkSaveContext context) {
        doStoreFileChunk(context);
        doSaveRecord(context);
    }

    /**
     * 判断所有分片均上传完成
     * @param context
     */
    private void doJudgeMergeFile(FileChunkSaveContext context) {
        QueryWrapper queryWrapper = Wrappers.query();
        queryWrapper.eq("identifier",context.getIdentifier());
        queryWrapper.eq("create_user",context.getUserId());
        int count = count(queryWrapper);
        if(count==context.getTotalChunks().intValue()){
            context.setMergeFlagEnum(MergeFlagEnum.READY);
        }
    }

    /**
     * 保存文件分片记录
     * @param context
     */
    private void doSaveRecord(FileChunkSaveContext context) {
        RPanFileChunk record = new RPanFileChunk();
        record.setId(IdUtil.get());
        record.setIdentifier(context.getIdentifier());
        record.setRealPath(context.getRealPath());
        record.setChunkNumber(context.getChunkNumber());
        record.setExpirationTime(DateUtil.offsetDay(new Date(), config.getChunkFileExpirationDays()));
        record.setCreateTime(new Date());
        record.setCreateUser(context.getUserId());
        if(!save(record)){
            throw new RPanBusinessException("文件分片上传失败");
        }
    }

    /**
     * 委托文件存储引擎 保存分片
     * @param context
     */
    private void doStoreFileChunk(FileChunkSaveContext context) {
       try{
           StoreFileChunkContext storeFileChunkContext = fileConverter.fileChunkSaveContext2StoreFileChunkContext(context);
           storeFileChunkContext.setInputStream(context.getFile().getInputStream());
           storageEngine.storeChunk(storeFileChunkContext);
           context.setRealPath(storeFileChunkContext.getRealPath());
       }catch (IOException e){
           e.printStackTrace();
           throw new RPanBusinessException("文件分片上传失败");
       }
    }




}
